<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>高压配电机房监测</title>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <link href="https://cdn.jsdelivr.net/npm/boxicons@2.0.7/css/boxicons.min.css" rel="stylesheet">
    <style>
        body {
            font-family: 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
            background: #f5f7fa;
            margin: 0;
            padding: 0;
        }
        .container {
            max-width: 1200px;
            margin: 40px auto;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 12px 0 rgba(0,0,0,.08);
            padding: 32px 24px 24px 24px;
        }
        .title {
            font-size: 22px;
            font-weight: bold;
            color: #1565C0;
            margin-bottom: 24px;
        }
        .section {
            margin-bottom: 28px;
        }
        .el-card__header {
            font-size: 16px;
            font-weight: 600;
            color: #303133;
        }
        .device-table {
            margin-top: 12px;
        }
        .alert-table {
            margin-top: 12px;
        }
        .point-map {
            width: 100%;
            height: 320px;
            background: #f5f7fa url('high-voltage-room-bg.png') center/cover no-repeat;
            border: 1px solid #ebeef5;
            border-radius: 8px;
            position: relative;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #909399;
            font-size: 18px;
        }
        .point-marker {
            position: absolute;
            width: 32px;
            height: 32px;
            background: #1565C0;
            color: #fff;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 18px;
            cursor: pointer;
            border: 2px solid #fff;
            box-shadow: 0 2px 8px rgba(21,101,192,0.15);
        }
        .dashboard-card {
            transition: transform 0.25s cubic-bezier(.4,2,.6,1);
            will-change: transform;
        }
        .dashboard-vertical {
            display: flex;
            flex-direction: column;
            gap: 0;
        }
        .alarm-stat-card {
            background: linear-gradient(90deg, #f5f7fa 60%, #e3f2fd 100%);
            border-radius: 14px;
            box-shadow: 0 2px 12px 0 rgba(21,101,192,0.06);
            padding-bottom: 18px;
        }
        .alarm-stat-title {
            font-size: 20px;
            font-weight: bold;
            color: #1a237e;
            letter-spacing: 1px;
            display: flex;
            align-items: center;
        }
        .alarm-stat-row {
            display: flex;
            justify-content: space-around;
            align-items: flex-end;
            margin-top: 18px;
            margin-bottom: 6px;
            gap: 12px;
        }
        .alarm-stat-item {
            flex: 1;
            background: #fff;
            border-radius: 10px;
            box-shadow: 0 1px 4px 0 rgba(21,101,192,0.04);
            padding: 18px 0 10px 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            min-width: 90px;
        }
        .alarm-stat-label {
            font-size: 15px;
            color: #607d8b;
            margin-bottom: 8px;
        }
        .alarm-stat-num {
            font-size: 36px;
            font-weight: bold;
            letter-spacing: 2px;
            line-height: 1.1;
            margin-bottom: 2px;
            transition: color 0.3s;
        }
        .alarm-total {
            color: #1a237e;
            text-shadow: 0 2px 8px #e3f2fd;
        }
        .alarm-unhandled {
            color: #C62828;
            text-shadow: 0 2px 8px #ffcdd2;
        }
        .alarm-handled {
            color: #2E7D32;
            text-shadow: 0 2px 8px #c8e6c9;
        }
        .chart-container {
            width: 100%;
            height: 260px;
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        .chart-full {
            width: 100%;
            height: 100%;
            min-height: 180px;
        }
        .el-button.center-text {
            display: flex !important;
            align-items: center;
            justify-content: center;
            font-size: 14px;
            font-weight: bold;
            height: 28px;
            min-width: 80px;
            border-radius: 0;
            padding: 0 18px;
            line-height: 28px;
        }
        .alarm-section-card {
            border: 2px solid #F56C6C !important;
            background: #FEF0F0 !important;
        }
    </style>
</head>
<body>
    <div id="high-voltage-room-monitor">
        <div class="container">
            <div class="title"><i class='bx bx-bolt'></i> 高压配电机房监测</div>
            <el-tabs v-model="activeTab">
                <!-- 1. 机房列表 -->
                <el-tab-pane label="机房列表" name="list">
                    <el-table :data="rooms" border stripe size="small">
                        <el-table-column prop="name" label="机房名称" width="180"></el-table-column>
                        <el-table-column prop="temp" label="温度"></el-table-column>
                        <el-table-column prop="humidity" label="湿度"></el-table-column>
                        <el-table-column prop="noise" label="噪声"></el-table-column>
                        <el-table-column prop="waterLeak" label="是否有水浸">
                            <template slot-scope="scope">
                                <el-tag :type="scope.row.waterLeak ? 'danger' : 'success'" size="mini">{{scope.row.waterLeak ? '是' : '否'}}</el-tag>
                            </template>
                        </el-table-column>
                        <el-table-column prop="offline" label="是否有设备离线">
                            <template slot-scope="scope">
                                <el-tag :type="scope.row.offline ? 'danger' : 'success'" size="mini">{{scope.row.offline ? '是' : '否'}}</el-tag>
                            </template>
                        </el-table-column>
                        <el-table-column prop="alert" label="是否有告警">
                            <template slot-scope="scope">
                                <el-tag :type="scope.row.alert ? 'danger' : 'success'" size="mini">{{scope.row.alert ? '是' : '否'}}</el-tag>
                            </template>
                        </el-table-column>
                        <el-table-column label="操作" width="220">
                            <template slot-scope="scope">
                                <div style="display: flex; flex-direction: row; gap: 12px; justify-content: center; align-items: center; width: 100%;">
                                    <el-button size="mini" type="primary" class="center-text" @click="openBindDialog(scope.row)">绑定信息</el-button>
                                    <el-button size="mini" type="success" class="center-text" style="min-width: 100px;" @click="openPointDialog(scope.row)">机房点位配置</el-button>
                                </div>
                            </template>
                        </el-table-column>
                    </el-table>
                </el-tab-pane>
                <!-- 2. 综合仪表盘 -->
                <el-tab-pane label="综合仪表盘" name="dashboard">
                    <div style="margin-bottom:18px;display:flex;align-items:center;gap:18px;">
                        <el-select v-model="dashboardRoom" placeholder="请选择机房" style="width:220px;">
                            <el-option v-for="room in rooms" :key="room.name" :label="room.name" :value="room.name"></el-option>
                        </el-select>
                    </div>
                    <div class="dashboard-vertical">
                        <el-card class="dashboard-card alarm-stat-card" shadow="hover" style="margin-bottom:28px;">
                            <div slot="header" class="alarm-stat-title">
                                <i class="el-icon-warning-outline" style="color:#C62828;margin-right:8px;"></i>告警统计
                            </div>
                            <div class="alarm-stat-row">
                                <div class="alarm-stat-item">
                                    <div class="alarm-stat-label">所有告警</div>
                                    <div class="alarm-stat-num alarm-total" id="alarm-total">0</div>
                                </div>
                                <div class="alarm-stat-item">
                                    <div class="alarm-stat-label">未处理</div>
                                    <div class="alarm-stat-num alarm-unhandled" id="alarm-unhandled">0</div>
                                </div>
                                <div class="alarm-stat-item">
                                    <div class="alarm-stat-label">已处理</div>
                                    <div class="alarm-stat-num alarm-handled" id="alarm-handled">0</div>
                                </div>
                            </div>
                        </el-card>
                    </div>
                </el-tab-pane>
                <!-- 3. 设备详情监控 -->
                <el-tab-pane label="设备详情监控" name="device">
                    <el-select v-model="selectedRoom" placeholder="请选择机房" style="margin-bottom:16px;width:220px;">
                        <el-option v-for="room in rooms" :key="room.name" :label="room.name" :value="room.name"></el-option>
                    </el-select>
                    <el-card class="section" shadow="hover" style="margin-bottom:18px;">
                        <div slot="header">环境状态</div>
                        <el-table :data="filteredDevices.filter(d=>d.type==='环境')" border stripe class="device-table" size="small">
                            <el-table-column prop="name" label="设备名称" width="120"></el-table-column>
                            <el-table-column prop="waterLeak" label="水浸情况" width="100">
                                <template slot-scope="scope">
                                    <el-tag :type="scope.row.waterLeak===true?'danger':'success'" size="mini">{{scope.row.waterLeak===true?'水浸':'非水浸'}}</el-tag>
                                </template>
                            </el-table-column>
                            <el-table-column prop="noise" label="室内噪音"></el-table-column>
                            <el-table-column prop="temp" label="室内温度"></el-table-column>
                            <el-table-column prop="humidity" label="室内湿度"></el-table-column>
                        </el-table>
                    </el-card>
                    <el-card class="section alarm-section-card" shadow="hover" style="margin-bottom:0; border:2px solid #F56C6C; background:#FEF0F0;">
                        <div slot="header" style="color:#C62828; font-weight:bold; display:flex; align-items:center;"><i class="el-icon-warning-outline" style="margin-right:8px;"></i>告警列表</div>
                        <el-table :data="filteredAlerts.filter(a=>a.device==='环境')" border stripe class="alert-table" size="small">
                            <el-table-column prop="device" label="设备"></el-table-column>
                            <el-table-column prop="type" label="告警类型"></el-table-column>
                            <el-table-column prop="status" label="状态">
                                <template slot-scope="scope">
                                    <el-tag :type="scope.row.status==='未处理'?'danger':'success'" size="mini">{{scope.row.status}}</el-tag>
                                </template>
                            </el-table-column>
                            <el-table-column prop="time" label="时间"></el-table-column>
                        </el-table>
                    </el-card>
                </el-tab-pane>
                <!-- 4. 机房点位图 -->
                <el-tab-pane label="机房点位图" name="map">
                    <el-select v-model="selectedRoom" placeholder="请选择机房" style="margin-bottom:16px;width:220px;">
                        <el-option v-for="room in rooms" :key="room.name" :label="room.name" :value="room.name"></el-option>
                    </el-select>
                    <el-card class="section" shadow="hover">
                        <div slot="header">机房点位图</div>
                        <div class="point-map">
                            <span v-if="!pointMarkers[selectedRoom]">暂无背景图和点位信息</span>
                            <template v-else>
                                <span style="color:#1565C0;">[背景图占位]</span>
                                <div v-for="(marker, idx) in pointMarkers[selectedRoom].filter(m=>m.type==='环境')" :key="idx" class="point-marker" :style="{left: marker.x+'%', top: marker.y+'%'}" :title="marker.device" @click="selectDevice(marker)">
                                    <div style="position:absolute;top:-28px;left:50%;transform:translateX(-50%);font-size:13px;font-weight:bold;color:#333;white-space:nowrap;">{{marker.device}}</div>
                                    <i :class="deviceImages[marker.device]" style="font-size:28px;"></i>
                                    <div style="position:absolute;bottom:-32px;left:50%;transform:translateX(-50%);display:flex;gap:4px;">
                                        <el-tag v-if="getDeviceAlertStatus(marker.device)" type="danger" size="mini">告警</el-tag>
                                        <el-tag v-else type="success" size="mini">正常</el-tag>
                                        <el-tag v-if="getDeviceOfflineStatus(marker.device)" type="danger" size="mini">离线</el-tag>
                                        <el-tag v-else type="success" size="mini">在线</el-tag>
                                    </div>
                                </div>
                            </template>
                        </div>
                        <div v-if="selectedDevice && selectedDeviceType==='环境'" class="device-detail-panel">
                            <el-card shadow="never" style="margin-top:18px;">
                                <div slot="header">{{selectedDevice.device}} 详情</div>
                                <el-table :data="getDeviceData(selectedDevice.device)" border stripe size="small">
                                    <el-table-column prop="name" label="设备名称" width="120"></el-table-column>
                                    <el-table-column prop="waterLeak" label="水浸情况"></el-table-column>
                                    <el-table-column prop="noise" label="室内噪音"></el-table-column>
                                    <el-table-column prop="temp" label="室内温度"></el-table-column>
                                    <el-table-column prop="humidity" label="室内湿度"></el-table-column>
                                </el-table>
                                <div style="margin-top:10px;">
                                    <b>告警列表</b>
                                    <el-table :data="getDeviceAlerts(selectedDevice.device)" border stripe size="mini" style="margin-top:6px;">
                                        <el-table-column prop="type" label="告警类型"></el-table-column>
                                        <el-table-column prop="status" label="状态"></el-table-column>
                                        <el-table-column prop="time" label="时间"></el-table-column>
                                    </el-table>
                                </div>
                            </el-card>
                        </div>
                    </el-card>
                </el-tab-pane>
            </el-tabs>
        </div>
        <!-- 机房绑定弹窗 -->
        <el-dialog :visible.sync="bindDialogVisible" title="机房绑定信息" width="600px" append-to-body>
            <el-form :model="bindForm" label-width="140px" size="small">
                <el-form-item label="机房名称">
                    <el-input v-model="bindForm.name" disabled></el-input>
                </el-form-item>
                <el-form-item label="绑定环境信息">
                    <el-select v-model="bindForm.envs" multiple filterable placeholder="请选择环境传感器">
                        <el-option v-for="item in allSensors" :key="item" :label="item" :value="item"></el-option>
                    </el-select>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="bindDialogVisible=false">取 消</el-button>
                <el-button type="primary" @click="saveBindInfo">确 定</el-button>
            </div>
        </el-dialog>
        <!-- 点位配置弹窗 -->
        <el-dialog :visible.sync="pointDialogVisible" title="机房点位配置" width="700px" append-to-body>
            <el-form label-width="120px" size="small">
                <el-form-item label="背景设置">
                    <el-radio-group v-model="pointBgMode">
                        <el-radio label="image">上传图片</el-radio>
                        <el-radio label="color">纯色背景</el-radio>
                    </el-radio-group>
                    <div v-if="pointBgMode==='image'" style="margin-top:8px;">
                        <el-upload class="upload-demo" drag action="#" :show-file-list="false" :on-change="handlePointBgUpload">
                            <i class="el-icon-upload"></i>
                            <div class="el-upload__text">将图片拖到此处，或<em>点击上传</em></div>
                        </el-upload>
                        <div v-if="pointBgUrl" style="margin-top:8px;"><img :src="pointBgUrl" style="max-width:100%;max-height:120px;border-radius:4px;"></div>
                    </div>
                    <div v-else style="margin-top:8px;">
                        <el-color-picker v-model="pointBgColor"></el-color-picker>
                        <span style="margin-left:12px;">当前颜色：<span :style="{background:pointBgColor,display:'inline-block',width:'32px',height:'16px',borderRadius:'4px',border:'1px solid #eee'}"></span></span>
                    </div>
                </el-form-item>
                <el-form-item label="设备点位配置">
                    <el-table :data="pointDevices" border size="mini">
                        <el-table-column label="设备" width="120">
                            <template slot-scope="scope">
                                <i :class="deviceImages[scope.row.name]" style="font-size:24px;color:#1565C0;margin-right:6px;vertical-align:middle;"></i>{{scope.row.name}}
                            </template>
                        </el-table-column>
                        <el-table-column label="类型" prop="type" width="80"></el-table-column>
                        <el-table-column label="X坐标" width="90">
                            <template slot-scope="scope">
                                <el-input v-model="scope.row.x" size="mini" placeholder="X"></el-input>
                            </template>
                        </el-table-column>
                        <el-table-column label="Y坐标" width="90">
                            <template slot-scope="scope">
                                <el-input v-model="scope.row.y" size="mini" placeholder="Y"></el-input>
                            </template>
                        </el-table-column>
                    </el-table>
                </el-form-item>
                <el-form-item label="点位预览">
                    <div style="position:relative;width:100%;height:220px;border-radius:8px;overflow:hidden;border:1px solid #ebeef5;background:#f5f7fa;">
                        <img v-if="pointBgMode==='image' && pointBgUrl" :src="pointBgUrl" style="width:100%;height:100%;object-fit:cover;position:absolute;left:0;top:0;z-index:1;">
                        <div v-else :style="{background:pointBgColor,width:'100%',height:'100%',position:'absolute',left:0,top:0,zIndex:1}"></div>
                        <div v-for="dev in pointDevices" :key="dev.name" :style="{position:'absolute',left:dev.x+'%',top:dev.y+'%',zIndex:2,transform:'translate(-50%,-50%)'}">
                            <i :class="deviceImages[dev.name]" style="font-size:36px;color:#1565C0;"></i>
                            <div style="text-align:center;font-size:12px;color:#333;">{{dev.name}}</div>
                        </div>
                    </div>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="pointDialogVisible=false">取 消</el-button>
                <el-button type="primary" @click="savePointInfo">确 定</el-button>
            </div>
        </el-dialog>
    </div>
    <script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.min.js"></script>
    <script>
        new Vue({
            el: '#high-voltage-room-monitor',
            data() {
                return {
                    activeTab: 'list',
                    selectedRoom: '',
                    rooms: [
                        { name: 'A栋高压配电机房', temp: '25℃', humidity: '55%', noise: '50dB', waterLeak: false, offline: false, alert: true },
                        { name: 'B栋高压配电机房', temp: '27℃', humidity: '53%', noise: '52dB', waterLeak: true, offline: true, alert: false }
                    ],
                    devices: [
                        { room: 'A栋高压配电机房', name: '高压开关柜1', type: '高压开关柜', voltage: '10kV', current: '200A', status: '运行' },
                        { room: 'A栋高压配电机房', name: '主变压器1', type: '主变压器', temp: '65℃', oilLevel: '80%', status: '正常' },
                        { room: 'A栋高压配电机房', name: '环境', type: '环境', waterLeak: false, noise: '50dB', temp: '25℃', humidity: '55%' },
                        { room: 'B栋高压配电机房', name: '高压开关柜1', type: '高压开关柜', voltage: '10kV', current: '180A', status: '待机' },
                        { room: 'B栋高压配电机房', name: '主变压器1', type: '主变压器', temp: '68℃', oilLevel: '75%', status: '正常' },
                        { room: 'B栋高压配电机房', name: '环境', type: '环境', waterLeak: true, noise: '52dB', temp: '27℃', humidity: '53%' }
                    ],
                    alerts: [
                        { room: 'A栋高压配电机房', device: '高压开关柜1', type: '过载', status: '未处理', time: '2024-06-01 10:30' },
                        { room: 'A栋高压配电机房', device: '主变压器1', type: '温度高', status: '已处理', time: '2024-05-31 16:20' },
                        { room: 'B栋高压配电机房', device: '高压开关柜1', type: '过载', status: '未处理', time: '2024-06-01 11:00' },
                        { room: 'B栋高压配电机房', device: '主变压器1', type: '油位低', status: '已处理', time: '2024-05-31 17:20' },
                        // 新增环境设备告警演示数据
                        { room: 'A栋高压配电机房', device: '环境', type: '温度过高', status: '未处理', time: '2024-06-02 09:30' },
                        { room: 'A栋高压配电机房', device: '环境', type: '水浸告警', status: '已处理', time: '2024-06-01 15:20' },
                        { room: 'B栋高压配电机房', device: '环境', type: '湿度异常', status: '未处理', time: '2024-06-02 10:10' }
                    ],
                    pointMarkers: {
                        'A栋高压配电机房': [
                            { device: '高压开关柜1', type: '高压开关柜', x: 20, y: 60 },
                            { device: '主变压器1', type: '主变压器', x: 60, y: 30 },
                            { device: '环境', type: '环境', x: 40, y: 50 }
                        ],
                        'B栋高压配电机房': [
                            { device: '高压开关柜1', type: '高压开关柜', x: 30, y: 50 },
                            { device: '主变压器1', type: '主变压器', x: 70, y: 40 },
                            { device: '环境', type: '环境', x: 50, y: 60 }
                        ]
                    },
                    bindDialogVisible: false,
                    bindForm: {
                        name: '',
                        switchgears: [],
                        transformers: [],
                        envs: []
                    },
                    allSwitchgears: ['高压开关柜1', '高压开关柜2'],
                    allTransformers: ['主变压器1', '主变压器2'],
                    allSensors: ['水浸传感器A', '噪音传感器A', '温度传感器A', '湿度传感器A'],
                    pointDialogVisible: false,
                    pointBgMode: 'image',
                    pointBgUrl: '',
                    pointBgColor: '#f5f7fa',
                    pointDevices: [],
                    deviceImages: {
                        '高压开关柜1': 'el-icon-switch-button',
                        '高压开关柜2': 'el-icon-switch-button',
                        '主变压器1': 'el-icon-cpu',
                        '主变压器2': 'el-icon-cpu',
                        '环境': 'el-icon-sunny',
                    },
                    dashboardRoom: '',
                    dashboardPeriod: 'day',
                    selectedDevice: null,
                    selectedDeviceType: '',
                }
            },
            computed: {
                filteredDevices() {
                    if (!this.selectedRoom) return [];
                    return this.devices.filter(d => d.room === this.selectedRoom);
                },
                filteredAlerts() {
                    if (!this.selectedRoom) return [];
                    return this.alerts.filter(a => a.room === this.selectedRoom);
                }
            },
            watch: {
                activeTab(val) {
                    if (val === 'dashboard') {
                        this.$nextTick(() => {
                            this.initDashboard();
                        });
                    }
                },
                dashboardRoom() {
                    this.updateDashboardStats();
                    this.renderBusbarVoltageChart();
                    this.renderMainTransformerTempChart();
                },
                dashboardPeriod() {
                    this.renderBusbarVoltageChart();
                    this.renderMainTransformerTempChart();
                }
            },
            mounted() {
                this.dashboardRoom = this.rooms[0]?.name || '';
                this.$nextTick(() => {
                    this.initDashboard();
                });
                this.animateDashboardNumbers();
            },
            methods: {
                openBindDialog(room) {
                    this.bindForm = {
                        name: room.name,
                        switchgears: [],
                        transformers: [],
                        envs: []
                    };
                    this.bindDialogVisible = true;
                },
                openPointDialog(room) {
                    this.pointDevices = [
                        { name: '高压开关柜1', type: '高压开关柜', x: 20, y: 60 },
                        { name: '主变压器1', type: '主变压器', x: 60, y: 30 },
                        { name: '环境', type: '环境', x: 40, y: 50 }
                    ];
                    this.pointBgMode = 'image';
                    this.pointBgUrl = '';
                    this.pointBgColor = '#f5f7fa';
                    this.pointDialogVisible = true;
                },
                saveBindInfo() {
                    this.$message.success('保存成功（演示）');
                    this.bindDialogVisible = false;
                },
                handlePointBgUpload(file) {
                    const reader = new FileReader();
                    reader.onload = e => {
                        this.pointBgUrl = e.target.result;
                    };
                    reader.readAsDataURL(file.raw);
                },
                savePointInfo() {
                    this.$message.success('点位配置保存成功（演示）');
                    this.pointDialogVisible = false;
                },
                animateDashboardNumbers() {
                    const total = 4, unhandled = 2, handled = 2;
                    this.animateNum('alarm-total', total);
                    this.animateNum('alarm-unhandled', unhandled);
                    this.animateNum('alarm-handled', handled);
                },
                animateNum(id, target) {
                    const el = document.getElementById(id);
                    if (!el) return;
                    let n = 0;
                    const step = Math.max(1, Math.floor(target / 30));
                    const timer = setInterval(() => {
                        n += step;
                        if (n >= target) {
                            n = target;
                            clearInterval(timer);
                        }
                        el.textContent = n;
                    }, 30);
                },
                initDashboard() {
                    this.updateDashboardStats();
                    this.renderBusbarVoltageChart();
                    this.renderMainTransformerTempChart();
                },
                updateDashboardStats() {
                    const room = this.dashboardRoom;
                    const alerts = this.alerts.filter(a => a.room === room);
                    const total = alerts.length;
                    const unhandled = alerts.filter(a => a.status === '未处理').length;
                    const handled = alerts.filter(a => a.status === '已处理').length;
                    this.animateNum('alarm-total', total);
                    this.animateNum('alarm-unhandled', unhandled);
                    this.animateNum('alarm-handled', handled);
                },
                renderBusbarVoltageChart() {
                    const chart = echarts.init(document.getElementById('busbar-voltage-chart'));
                    const hours = Array.from({length: 24}, (_, i) => i+1+':00');
                    const data = Array.from({length: 24}, () => (9500+Math.random()*1000).toFixed(0));
                    chart.resize();
                    chart.setOption({
                        xAxis: { type: 'category', data: hours, boundaryGap: false },
                        yAxis: { type: 'value', min: 9000, max: 11000, axisLabel: { formatter: '{value} V' } },
                        series: [{
                            data,
                            type: 'line',
                            smooth: true,
                            areaStyle: { color: '#90caf9' },
                            lineStyle: { color: '#1565C0', width: 2 },
                            symbol: 'circle',
                            symbolSize: 6
                        }],
                        tooltip: { trigger: 'axis' },
                        grid: { left: 40, right: 20, top: 30, bottom: 30 },
                        title: { text: '', left: 'center', top: 0, textStyle: { fontSize: 14 } }
                    });
                },
                renderMainTransformerTempChart() {
                    const chart = echarts.init(document.getElementById('main-transformer-temp-chart'));
                    const hours = Array.from({length: 24}, (_, i) => i+1+':00');
                    const data = Array.from({length: 24}, () => (60+Math.random()*10).toFixed(1));
                    chart.resize();
                    chart.setOption({
                        xAxis: { type: 'category', data: hours, boundaryGap: false },
                        yAxis: { type: 'value', min: 50, max: 80, axisLabel: { formatter: '{value} ℃' } },
                        series: [{
                            data,
                            type: 'line',
                            smooth: true,
                            areaStyle: { color: '#ffe082' },
                            lineStyle: { color: '#fbc02d', width: 2 },
                            symbol: 'circle',
                            symbolSize: 6
                        }],
                        tooltip: { trigger: 'axis' },
                        grid: { left: 40, right: 20, top: 30, bottom: 30 },
                        title: { text: '', left: 'center', top: 0, textStyle: { fontSize: 14 } }
                    });
                },
                selectDevice(marker) {
                    this.selectedDevice = marker;
                    this.selectedDeviceType = marker.type;
                },
                getDeviceData(name) {
                    return this.devices.filter(d => d.room === this.selectedRoom && d.name === name);
                },
                getDeviceAlerts(name) {
                    return this.alerts.filter(a => a.room === this.selectedRoom && a.device === name);
                },
                getDeviceAlertStatus(name) {
                    return this.alerts.some(a => a.room === this.selectedRoom && a.device === name && a.status === '未处理');
                },
                getDeviceOfflineStatus(name) {
                    const dev = this.devices.find(d => d.room === this.selectedRoom && d.name === name);
                    return dev && dev.offline === true;
                }
            }
        });
    </script>
</body>
</html> 